﻿using System.ComponentModel;
using System.Windows;
using System;


namespace PDO.UI.Core
{
    public class BaseView : BaseControl, IBaseView, INotifyPropertyChanged
    {
        private BasePM _PM;

        public event EventHandler IsReadOnlyChanged;

        public BaseView()
        {
            this.Unloaded += new System.Windows.RoutedEventHandler(BaseView_Unloaded);
            this.LostFocus += new System.Windows.RoutedEventHandler(BaseView_LostFocus);
            this.IsVisibleChanged += new DependencyPropertyChangedEventHandler(BaseView_IsVisibleChanged);
        }


        public bool IsReadOnly
        {
            get { return (bool)GetValue(IsReadOnlyProperty); }
            set { SetValue(IsReadOnlyProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsReadOnly.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsReadOnlyProperty =
            DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(BaseView),
               new FrameworkPropertyMetadata(new PropertyChangedCallback(IsReadOnlyProperty_Changed)));


        private static void IsReadOnlyProperty_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            BaseView bv = ((BaseView)sender);

            // Apply readonly value from control onto PM 
            if (null != bv.BasePM)
            {
                bv.BasePM.IsReadOnly = bv.IsReadOnly;
            }
        }

     

        void BaseView_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
            {
                bool isVisible = (bool)e.NewValue;
                if (isVisible)
                {
                    this.InitializeDataContext();
                }
            }
        }

        public virtual void InitializeDataContext()
        {
            // NOTE: Cannot make this an abstract function, since xaml designer cannot work with abstract classes.

            //if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
            //{
            //    throw new NotImplementedException("You must implement InitializeDataContext() in your BaseView derived view class.");
            //}
        }

        void BaseView_LostFocus(object sender, System.Windows.RoutedEventArgs e)
        {
            //throw new System.NotImplementedException();
        }

        /// <summary>
        /// This event handler is called whenever this view is "disconnected" from the 
        /// active view pane; i.e. when it is navigated away from.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void BaseView_Unloaded(object sender, System.Windows.RoutedEventArgs e)
        {
            // throw new System.NotImplementedException();
        }

        public BasePM BasePM
        {
            get { return _PM; }
            set
            {
                _PM = value;
                OnBasePMChanged();
                OnPropertyChanged("BasePM");
            }
        }

        public virtual void OnBasePMChanged()
        {
        }

        /// <summary>
        /// Provide an opportunity to shut down view prior to closing.  
        /// Note that a view may often be navigated away from, but that is *not* a Close.  
        /// There is also an UnLoaded event that you can subscribed to that fires *after* 
        /// the control has been unloaded from its parent element tree.
        /// </summary>
        /// <returns>true to allow view to close, false otherwise</returns>
        public virtual bool OnClose()
        {
            return true; // allow close
        }

        /// <summary>
        /// Set e.Cancel = true to cancel navigation away from your View.
        /// </summary>
        /// <param name="sender">sender</param>
        /// <param name="e">CancelEventArgs </param>
        public virtual void OnNavigatingAway(object sender, CancelEventArgs e)
        {
            // In derived class, override and set e.Cancel = true to cancel navigation away from your View.
        }


        #region INotifyPropertyChanged Members

        /// <summary>
        /// Raise PropertyChanged event for a specified property.
        /// </summary>
        /// <param name="propertyName"></param>
        public void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(
                  this,
                  new PropertyChangedEventArgs(propertyName)
                );
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

    }
}
